package cn.openea.perpartner.meily.web.service.logistics.businessModule;

import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.common.core.utils.SpringContextUtils;
import cn.openea.perpartner.common.core.utils.StringUtils;
import cn.openea.perpartner.meily.constant.enums.ExpressCompany;
import cn.openea.perpartner.meily.constant.enums.LogisticsModule;
import cn.openea.perpartner.meily.eventlistener.event.SyncLogisticsEvent;
import cn.openea.perpartner.meily.thirdparty.ExpressServiceApi;
import cn.openea.perpartner.meily.web.entity.LogisticsInfo;
import cn.openea.perpartner.meily.web.entity.dto.LogisticsDTOFactory;
import cn.openea.perpartner.meily.web.service.ILogisticsInfoService;
import cn.openea.perpartner.meily.web.service.logistics.LogisticsQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * @author ysk
 * @version 1.0.1
 * @Description TODO
 * @createTime 2023年05月11日 01:50:00
 */
@Slf4j
@Component
public abstract class LogisticsModelAbstractService implements LogisticsModuleService {

    @Resource
    private ExpressServiceApi expressServiceApi;
    @Resource
    private ApplicationContext applicationContext;
    @Resource
    private LogisticsQuery logisticsQuery;
    @Resource
    private ILogisticsInfoService logisticsInfoService;

    /**
     * 同步物流
     *
     * @param obj            模块对应的实体
     * @param expressCompany 快递公司 可以为null
     * @param courierNumber  快递单号
     * @param phone          手机号
     * @param logisticsId    物流信息编号 可以为null
     * @return ExpressCompany 物流对应的快递公司
     */
    protected ExpressCompany synchLogistics(Object obj, ExpressCompany expressCompany, String courierNumber, String phone,
                                            String logisticsId) {
        if (obj == null) {
            throw new ServiceException("数据异常");
        }
        LogisticsDTOFactory.LogisticsRealTimeDTO logisticsRealTimeDTO = expressServiceApi
                .realTimeLogistics(expressCompany,
                        courierNumber,
                        phone);
        if (expressCompany == null || !expressCompany.getCode().equals(logisticsRealTimeDTO.getCom())) {
            // 以物流查询返回的接口为准
            if (StringUtils.isBlank(logisticsRealTimeDTO.getCom())){
                // 为空可能刚刚发货，没有物流,调用接口去匹配物流
                expressCompany = expressServiceApi.getExpressCompany(courierNumber);
            }else {
                expressCompany = ExpressCompany.getByCode(logisticsRealTimeDTO.getCom());
            }
        }
        // 到这里了 物流公司还为空
        if (expressCompany == null){
            throw new ServiceException("不支持此快递公司");
        }
        // 保存使用监听的方式 需要同步
        applicationContext.publishEvent(new SyncLogisticsEvent(this, obj, logisticsRealTimeDTO, logisticsId));
        // 返回物流公司
        return expressCompany;
    }

    /**
     * 校验是否为最终物流信息
     *
     * @return LogisticsInfo 最终物流信息
     */
    protected LogisticsInfo checkEventuallyLogistics(LogisticsModule logisticsModule, String moduleId) {
        LogisticsInfo logisticsInfo = logisticsQuery.findByModuleAndModuleId(logisticsModule, moduleId);
        if (logisticsInfo != null && logisticsInfo.isSing()) {
            if (StringUtils.isBlank(logisticsInfo.getDynamicContext())) {
                // 已签收，但是物流信息为空，可能是历史数据 同步物流到自己表里面
                SpringContextUtils.getApplicationContext()
                        .publishEvent(new SyncLogisticsEvent(this, logisticsInfo));
            }
        }
        return logisticsInfo;
    }

    @Override
    public void businessDelayedReceipt(String id, int days) {
        LogisticsInfo logisticsInfo = Optional.ofNullable(findByModuleId(id))
                .orElseThrow(() -> new ServiceException("物流信息不存在"));
        logisticsInfoService.businessDelayedReceipt(logisticsInfo.getId(), days + logisticsInfo.getDelayedReceiptDays());
    }

    @Override
    public void businessStatusFinish(String moduleId) {
    }
}
